package main

import (
	"context"
	"fmt"
	"gorm_pool"
	"log"
	"sync"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm_pool/databases"
)

// 测试连接池
func testWithPool() {
	// 配置连接池选项
	opts := gorm_pool.Options{
		Type:            databases.MySQL,                                                   // 数据库类型为 MySQL
		Args:            "root:admin@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True", // 数据库连接参数
		KeepConn:        2,                                                                 // 保持的空闲连接数为 2
		Capacity:        5,                                                                 // 连接池的最大容量为 5
		MaxWaitDuration: 2000 * time.Millisecond,                                           // 获取连接的最大等待时间为 2000 毫秒
	}

	// 创建一个上下文，用于控制连接池的生命周期
	ctx, canc := context.WithCancel(context.Background())
	// 创建连接池实例
	p, err := gorm_pool.NewPool(ctx, opts)
	if err != nil {
		log.Println(err) // 如果创建连接池失败，打印错误信息
		return
	}
	defer p.Close() // 函数结束时关闭连接池
	defer canc()    // 函数结束时取消上下文

	var wg sync.WaitGroup
	start := time.Now() // 记录开始时间
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(idx int) {
			defer wg.Done()
			conn, err := p.Get() // 从连接池获取连接
			if err != nil {
				fmt.Println(err) // 如果获取连接失败，打印错误信息
				return
			}
			time.Sleep(100 * time.Millisecond) // 模拟使用连接 100 毫秒
			p.Put(conn)                        // 将连接放回连接池
		}(i)
	}
	wg.Wait()                                             // 等待所有 goroutine 完成
	elapsed := time.Since(start)                          // 计算总耗时
	fmt.Printf("Using pool, elapsed time: %s\n", elapsed) // 打印使用连接池的总耗时
}

// 不使用连接池
func testWithoutPool() {
	dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True" // 数据库连接字符串
	var wg sync.WaitGroup
	start := time.Now() // 记录开始时间
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(idx int) {
			defer wg.Done()
			db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) // 直接打开数据库连接
			if err != nil {
				fmt.Println(err) // 如果打开连接失败，打印错误信息
				return
			}
			time.Sleep(100 * time.Millisecond) // 模拟使用连接 100 毫秒
			sqlDB, _ := db.DB()
			sqlDB.Close() // 关闭数据库连接
		}(i)
	}
	wg.Wait()                                               // 等待所有 goroutine 完成
	elapsed := time.Since(start)                            // 计算总耗时
	fmt.Printf("Without pool, elapsed time: %s\n", elapsed) // 打印不使用连接池的总耗时
}

func main() {
	testWithPool()    // 测试使用连接池的情况
	testWithoutPool() // 测试不使用连接池的情况
}
